import java.io.*;

public class NetworkTest {

	public static void main(String[] args) {
		//Data
		double[][][] data = new double[5000][3][];
		try {
			BufferedReader x = new BufferedReader(new FileReader("x.dat"));
			BufferedReader y = new BufferedReader(new FileReader("y.dat"));
			
			for (int i = 0; i < 5000; i++) {
				String[] da = x.readLine().split(",");
				data[i][0] = new double[da.length];
				data[i][1] = new double[10];
				data[i][2] = new double[10];
				for (int j = 0; j < da.length; j++) {
					data[i][0][j] = Double.parseDouble(da[j]);
				}
				double l = Integer.parseInt(y.readLine()) - 1;
				for (int j = 0; j < 10; j++) {
					if (j == l) {
						data[i][1][j] = 1;
					} else {
						data[i][1][j] = 0;
					}
					data[i][2][j] = j;
				}
			}	
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
		//Network
		String[][] l = new String[3][];
		l[0] = new String[401];
		l[0][0] = "B";
		for (int i = 1; i < 401; i++) {
			l[0][i] = "L";
		}
		l[1] = new String[26];
		l[1][0] = "B";
		for (int i = 1; i < 26; i++) {
			l[1][i] = "S";
		}
		l[2] = new String[10];
		for (int i = 0; i < 10; i++) {
			l[2][i] = "S";
		}
		NeuralNet net = new NeuralNet(NeuralNet.quickCPPN(l), 0);
		
		//Experiment
		run(data, net);
		
		//When running this, disable update weights in train network
		//check(data, net);
	}
	
	public static void run(double[][][] data, NeuralNet net) {
		//Training
		try {
			BufferedWriter o = new BufferedWriter(new FileWriter("error.csv"));
			for (int i = 0; i < 5000; i++) {
				o.write(i+",");
				o.write((net.trainNetwork(data, 1.0)/5000)+"\n");
				System.out.println(i);
			}
			o.close();
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
		//Evaluation
		double t = 0;
		for (int i = 0; i < 5000; i++) {
			net.processInput(data[i][0]);
			double[] o = net.getOutputs();
			int mi = -1;
			int tl = -1;
			double mv = Double.NEGATIVE_INFINITY;
			for (int j = 0; j < o.length; j++) {
				if (o[j] > mv) {
					mi = j;
					mv = o[j];
				}
				if (data[i][1][j] > 0.5) {
					tl = j;
				}
			}
			if (tl == mi) {
				t += (1.0/5000.0);
			}
		}
		System.out.println("Precision: "+t);
	}
	
	public static void check(double[][][] data, NeuralNet net) {
		net.trainNetwork(data, 1.0);
		double eps = 0.001;
		double t = 0;
		
		for (int i = 0; i < net.size(); i++) {
			for (int j = 0; j < net.size(i); j++) {
				Node n = net.getNode(i, j);
				for (int k = 0; k < n.size(); k++) {
					double w = n.getWeight(k);
					double d = n.getDiff(k)/5000;
					n.setWeight(k, w - eps);
					double r1 = net.evaluate(data)/5000;
					n.setWeight(k, w + eps);
					double r2 = net.evaluate(data)/5000;
					n.setWeight(k, w);
					double g = (r1 - r2) / (2*eps);
					t += ((double) Math.abs(g - d)) / 5000;
					System.out.println(d+"\t"+g+"\t"+(g/d));
				}
			}
		}
		System.out.println("Average err: "+t);
	}
}
